#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <string.h>

#define MSGKEY 1234 // 队列的Key

const long id1 = 211; // 从父进程发向子进程的 队列类型
const long id2 = 311; // 从子进程发向父进程的 队列类型

typedef struct msgbuf // 定义的消息结构
{
    long mtype;
    int mtext;
} msgbuf;

int main()
{
    int qid; // 消息队列号
    qid = msgget(MSGKEY, IPC_EXCL);
    if (qid < 0) // 先判断存不存在 不存在再创建
    {
        qid = msgget(MSGKEY, IPC_CREAT | 0666); // 创建一个消息队列 设置权限
    }
    else
    {
        printf("Msg Exist!, Qid : %d\n", qid); // 队列已经存在
    }

    // 创建子进程
    pid_t pid = fork();

    if (pid > 0) // 父进程
    {
        msgbuf myBuf;
        myBuf.mtype = id1;
        // strcpy(myBuf.mtext, "hello thank you your message!");

        printf("Parent process , pid : %d\n", getpid());

        int ll;

        int num[] = {2, 4, 7, 6, 8, 9, 12, 20, 43, 23}; // 定义一个整型数组，初始化10个整数

        for (ll = 0; ll < 10; ll++) // 循环把10个整数发送给子进程
        {
            myBuf.mtext = num[ll];
            if (msgsnd(qid, &myBuf, sizeof(myBuf.mtext), 0) == -1) // 将信息挂载到消息队列里
            {
                perror("parent msgsnd");
                return -1;
            }
            else
            {
                printf("Parent Send Data Success! Pid : %d   Data:%d \n", getpid(), myBuf.mtext);
            }
        }

        usleep(3);

        if (msgrcv(qid, &myBuf, sizeof(myBuf.mtext), id2, 0) == -1) // 接收子进程发的数据
        {
            printf("Parent Receive Data Failed! Pid : %d\n", getpid());
        }
        printf("Parent Receive Data Success! Pid: %d  Sum Data: %d \n", getpid(), myBuf.mtext);

        waitpid(pid, NULL, 0); // 等待子进程退出

        printf("Parent Exit! Pid : %d\n", getpid());
    }
    else if (pid == 0) // 子进程
    {
        msgbuf myBuf;

        sleep(2);
        printf("Child process , pid : %d\n", getpid());

        int num = 0;

        int ll;
        for (ll = 0; ll < 10; ll++) // 循环把10个整数接收到
        {
            if (msgrcv(qid, &myBuf, sizeof(myBuf.mtext), id1, 0) == -1)
            {
                printf("Child Receive Data Failed! Pid : %d\n", getpid());
            }
            printf("Child Receive Data Success! Pid: %d    Data: %d \n", getpid(), myBuf.mtext);
            num += myBuf.mtext; // 把接收到的值累计到 num变量中
        }
        printf("Child Receive Data Sum: %d\n", num);

        // 子进程把计算结果发送到队列中
        myBuf.mtext = num;
        myBuf.mtype = id2;
        if (msgsnd(qid, &myBuf, sizeof(myBuf.mtext), 0) == -1) // 将信息挂载到消息队列里
        {
            perror("parent msgsnd");
            return -1;
        }
        else
        {
            printf("Child Send Sum Data Success! Pid : %d   Sum:%d\n", getpid(), myBuf.mtext);
        }
    }
    return 0;
}